package com.zhuzi;

import com.zhuzi.utils.DateUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.cli.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.http.client.fluent.Request;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

/**
 * @Author: MI
 * @Date: 2021/10/23/21:26
 * @Description:
 */
public class Jsl {
    //https://www.jisilu.cn/question/347472
    private static String questionUrl = "https://www.jisilu.cn/question/437722";
    private static String questionPage = "https://www.jisilu.cn/question/id-%s__sort_key-__sort-ASC__uid-__page-%s";
    private static String urlForComment = "https://www.jisilu.cn/question/ajax/get_answer_comments/answer_id-%s";

    public static void main(String[] args) {
        //https://www.jisilu.cn/question/347472
        CommandLine commandLine = parseParam(args);

        String url = questionUrl;
        if (commandLine.hasOption("u")) {
            url = commandLine.getOptionValue("u");
        }

        String html = httpGet(url);
        Element body = Jsoup.parse(html);
        JslQuestion jslQuestion = JslQuestion.parse(body);
        for (int i = 1; i <= (jslQuestion.getNumOfReply() + 99) / 100; i++) {
            String name = FilenameUtils.getName(url);
            if (i != 1) {
                body = Jsoup.parse(httpGet(String.format(questionPage, name, i)));
            }
            removeOther(body);
            Elements replyEles = body.select(".aw-dynamic-topic");
            //获取回复的 评论
            for (Element replyDiv : replyEles.get(0).children()) {
                addComment(replyDiv);
            }
            File file = new File(".", name + "-" + StringUtils.leftPad(i + "", 2, "0") + jslQuestion.getTitle().trim() + ".html");
            try {
                FileUtils.writeStringToFile(file, body.html(), StandardCharsets.UTF_8);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static CommandLine parseParam(String[] args) {
        Option opt1 = new Option("u", "url", true, "spring 源码位置(eg:https://www.jisilu.cn/question/347472)");
        opt1.setRequired(false);
        Options options = new Options();
        options.addOption(opt1);

        CommandLine cli = null;
        CommandLineParser cliParser = new DefaultParser();
        HelpFormatter helpFormatter = new HelpFormatter();

        try {
            cli = cliParser.parse(options, args);
        } catch (ParseException e) {
            // 解析失败是用 HelpFormatter 打印 帮助信息
            helpFormatter.printHelp(">>>>>>   cli options", options);
            e.printStackTrace();
        }
        return cli;
    }

    private static void addComment(Element replyDiv) {
        String idStr = StringUtils.getDigits(replyDiv.attr("id"));
        //评论 数量
        Elements commentCount = replyDiv.select(".aw-add-comment");
        String digits = StringUtils.getDigits(commentCount.text());
        //有评论
        if (!StringUtils.equals("0", digits)) {
            String dataId = commentCount.get(0).attr("data-id");
            String ajaxComment = httpGet(String.format(urlForComment, dataId));

            // id  从这里取数字，replyDiv.attr("id")
            Element commentBox = new Element("div").attr("class", "aw-comment-box").attr("id", "aw-comment-box-answer-" + (idStr));
            Element sondDiv = new Element("div").attr("class", "aw-comment-list").append(ajaxComment);
            commentBox.appendChild(sondDiv);

            replyDiv.appendChild(commentBox);

        }

    }

    @Setter
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class JslQuestion {
        /**
         * 地址
         */
        private String url;
        /**
         * 回复数量
         */
        private int numOfReply;

        /**
         * 标题
         */
        private String title;

        /**
         * 发布时间
         */
        private LocalDateTime publishTime;
        /**
         * 最后修改时间
         */
        private LocalDateTime modifiedTime;

        public static JslQuestion parse(Element ele) {
            Elements select = ele.select(".aw-mod-head");
            String title = select.get(0).getElementsByTag("h1").get(0).text();
            String replayOriginal = select.get(1).getElementsByTag("h2").text();
            String digits = StringUtils.getDigits(replayOriginal);
            int replyNum = 0;
            if (StringUtils.isNotBlank(digits)) {
                replyNum = Integer.parseInt(digits);
            }

            String text = ele.select(".aw-question-detail-meta div>span").text();
            String[] dateSplit = StringUtils.split(text, "时间|最后修改|发表");
            LocalDateTime publishDate = DateUtils.parseJslQuesPublish(dateSplit[0].trim());

            JslQuestion jslQuestion = new JslQuestion();
            jslQuestion.setTitle(title);
            jslQuestion.setNumOfReply(replyNum);
            jslQuestion.setPublishTime(publishDate);
            if (dateSplit.length > 1) {
                LocalDateTime modifyDate = DateUtils.parseJslQuesPublish(dateSplit[1].trim());
                jslQuestion.setModifiedTime(modifyDate);
            }
            return jslQuestion;
        }

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.NO_CLASS_NAME_STYLE);
        }
    }

    /**
     * 移除其其它元素
     *
     * @param root 文档
     */
    public static void removeOther(Element root) {
        //log 注册登录 右侧相关问题  回复编辑位置 底部位置  二维码
        String[] delClass = {".aw-logo", ".aw-login-register", ".aw-text-align-justify", ".aw-mod-replay-box", ".aw-footer-wrap", ".scanWeiXinWD"};
        for (String aClass : delClass) {
            root.select(aClass).remove();
        }
    }

    public static String httpGet(String url) {
        try {
            String html = Request.Get(url)
                    .connectTimeout(3 * 1000)
                    .socketTimeout(3 * 1000)
                    .execute().returnContent().asString(StandardCharsets.UTF_8);
            return html;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

}
